using System;
using System.Threading.Tasks;
using BanZuiCloudControlAgent.Core.Mqtt.Models;
using BanZuiCloudControlAgent.Core.Mqtt.Sender;
using BanZuiCloudControlAgent.Core.Tasks.Base;
using BanZuiCloudControlAgent.Core.Tasks.Enums;
using BanZuiCloudControlAgent.Core.Tasks.Models;
using BanZuiCloudControlAgent.Core.Tasks.Queue;
using BanZuiCloudControlAgent.Core.Tasks.Specific.QQ;
using BanZuiCloudControlAgent.Core.Tasks.Specific.System;
using BanZuiCloudControlAgent.Core.Tasks.Utils;
using BanZuiCloudControlAgent.Utils.Logging;
using System.Collections.Generic; // Added for Dictionary
using System.Linq; // Added for Where, Any, Select

namespace BanZuiCloudControlAgent.Core.Tasks.Handlers
{
    /// <summary>
    /// 任务分发器，负责将MQTT消息转换为具体任务并加入队列
    /// </summary>
    public class TaskDispatcher
    {
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly Logger _logger;
        
        /// <summary>
        /// 任务队列
        /// </summary>
        private readonly TaskQueue _taskQueue;
        
        /// <summary>
        /// 设备码
        /// </summary>
        private readonly string _deviceCode;
        
        /// <summary>
        /// 任务互斥管理器
        /// </summary>
        private readonly TaskMutexManager _mutexManager;
        
        /// <summary>
        /// 消息发送中间件
        /// </summary>
        private MessageSenderMiddleware _messageSender;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="taskQueue">任务队列</param>
        /// <param name="deviceCode">设备码</param>
        /// <param name="messageSender">消息发送中间件</param>
        public TaskDispatcher(Logger logger, TaskQueue taskQueue, string deviceCode, MessageSenderMiddleware messageSender = null)
        {
            _logger = logger;
            _taskQueue = taskQueue;
            _deviceCode = deviceCode;
            _messageSender = messageSender;
            _mutexManager = new TaskMutexManager();
        }
        
        /// <summary>
        /// 设置消息发送中间件
        /// </summary>
        /// <param name="messageSender">消息发送中间件</param>
        public void SetMessageSender(MessageSenderMiddleware messageSender)
        {
            _messageSender = messageSender;
        }
        
        /// <summary>
        /// 处理任务下发消息
        /// </summary>
        /// <param name="taskDispatch">任务下发消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> DispatchTaskAsync(TaskDispatchModel taskDispatch)
        {
            var payload = taskDispatch.GetPayload();
            if (payload == null)
            {
                _logger.Warn("任务负载为空或格式不正确");
                return null;
            }
            
            // 根据任务类型创建具体任务
            BaseTask task = CreateTask(payload);
            if (task == null)
            {
                _logger.Warn($"不支持的任务类型: {payload.TaskType}");
                return null;
            }
            
            // 根据操作类型处理任务
            switch (payload.Operation?.ToUpper())
            {
                case "START":
                    // 检查是否有相同类型的任务正在执行
                    if (ShouldDiscardTask(task))
                    {
                        _logger.Warn($"已有相同类型的任务正在执行，丢弃任务: {task.TaskId}, 类型: {task.TaskType}");
                        
                        // 上报任务被丢弃的通知
                        await ReportTaskDiscardedAsync(task, "已有相同类型的任务正在执行");
                        
                        return task; // 返回任务对象，但不加入队列
                    }
                    
                    await _taskQueue.EnqueueAsync(task);
                    break;
                case "PAUSE":
                    await _taskQueue.PauseTaskAsync(payload.TaskId);
                    break;
                case "RESUME":
                    await _taskQueue.ResumeTaskAsync(payload.TaskId);
                    break;
                case "STOP":
                    await _taskQueue.CancelTaskAsync(payload.TaskId);
                    break;
                default:
                    _logger.Warn($"不支持的操作类型: {payload.Operation}");
                    return null;
            }
            
            return task;
        }
        
        /// <summary>
        /// 检查是否应该丢弃任务（当有相同类型的任务正在执行或在队列中时）
        /// </summary>
        /// <param name="task">要检查的任务</param>
        /// <returns>如果应该丢弃任务，则返回true；否则返回false</returns>
        private bool ShouldDiscardTask(BaseTask task)
        {
            // 获取所有任务（包括运行中和队列中的任务）
            var allTasks = _taskQueue.GetAllTasks();
            
            // 检查是否有相同类型的任务
            var sameTypeTasks = allTasks.Where(t => 
                t.TaskType == task.TaskType && 
                t.TaskId != task.TaskId && 
                (t.Status == TaskState.Running || t.Status == TaskState.Pending || t.Status == TaskState.Paused)
            ).ToList();
            
            // 如果找到相同类型的任务，则应该丢弃新任务
            if (sameTypeTasks.Any())
            {
                _logger.Warn($"已存在相同类型的任务: {task.TaskType}, 当前任务ID: {task.TaskId}, 已存在任务ID: {string.Join(", ", sameTypeTasks.Select(t => t.TaskId))}");
                return true;
            }
            
            // 如果没有相同类型的任务，还需要检查任务组是否有可用槽位
            TaskGroup taskGroup = TaskGroupHelper.GetTaskGroup(task.TaskType);
            bool hasAvailableSlot = _mutexManager.HasAvailableSlot(taskGroup);
            
            // 如果没有可用槽位，说明有相同组的任务正在执行
            if (!hasAvailableSlot)
            {
                _logger.Warn($"任务组 {taskGroup} 没有可用槽位，丢弃任务: {task.TaskId}, 类型: {task.TaskType}");
                return true;
            }
            
            return false;
        }
        
        /// <summary>
        /// 上报任务被丢弃的通知
        /// </summary>
        /// <param name="task">被丢弃的任务</param>
        /// <param name="reason">丢弃原因</param>
        /// <returns>是否上报成功</returns>
        private async Task<bool> ReportTaskDiscardedAsync(BaseTask task, string reason)
        {
            if (_messageSender == null)
            {
                _logger.Warn("消息发送中间件未设置，无法上报任务丢弃通知");
                return false;
            }
            
            try
            {
                // 创建包含丢弃原因的数据字典
                var data = new Dictionary<string, object>
                {
                    { "DiscardReason", reason },
                    { "TaskType", task.TaskType.ToString() }
                };
                
                // 使用消息发送中间件发送任务失败报告
                return await _messageSender.SendTaskFailedReportAsync(
                    task.TaskId,
                    task.TaskType.ToString(),
                    reason,
                    data
                );
            }
            catch (Exception ex)
            {
                _logger.Error($"上报任务丢弃通知失败: {ex.Message}", ex);
                return false;
            }
        }
        
        /// <summary>
        /// 处理更新任务消息
        /// </summary>
        /// <param name="updateTask">更新任务消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> DispatchUpdateTaskAsync(UpdateTaskModel updateTask)
        {
            var payload = updateTask.GetPayload();
            if (payload == null)
            {
                _logger.Warn("更新任务负载为空或格式不正确");
                return null;
            }
            
            // 创建更新任务
            var task = new UpdateTask
            {
                TaskId = Guid.NewGuid().ToString(),
                TaskType = TaskType.Update,
                Priority = TaskPriority.High,
                Parameters = new System.Collections.Generic.Dictionary<string, object>
                {
                    { "downloadUrl", payload.DownloadUrl },
                    { "version", payload.Version },
                    { "forceUpdate", payload.ForceUpdate },
                    { "description", payload.Description },
                    { "releaseTime", payload.ReleaseTime }
                }
            };
            
            // 检查是否有相同类型的任务正在执行
            if (ShouldDiscardTask(task))
            {
                _logger.Warn($"已有更新任务正在执行，丢弃任务: {task.TaskId}");
                
                // 上报任务被丢弃的通知
                await ReportTaskDiscardedAsync(task, "已有更新任务正在执行");
                
                return task; // 返回任务对象，但不加入队列
            }
            
            // 将任务加入队列
            await _taskQueue.EnqueueAsync(task);
            
            return task;
        }
        
        /// <summary>
        /// 处理配置消息
        /// </summary>
        /// <param name="configModel">配置消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> DispatchConfigTaskAsync(ConfigModel configModel)
        {
            var payload = configModel.GetPayload();
            if (payload == null)
            {
                _logger.Warn("配置负载为空或格式不正确");
                return null;
            }
            
            // 创建配置任务
            var task = new ConfigTask
            {
                TaskId = Guid.NewGuid().ToString(),
                TaskType = TaskType.Config,
                Priority = TaskPriority.Normal,
                Parameters = new System.Collections.Generic.Dictionary<string, object>
                {
                    { "statusReportInterval", payload.StatusReportInterval },
                    { "idleStatusReportInterval", payload.IdleStatusReportInterval },
                    { "offlineThreshold", payload.OfflineThreshold },
                    //{ "logLevel", payload.LogLevel },
                    { "logUploadInterval", payload.LogUploadInterval },
                    { "enableAutoUpdate", payload.EnableAutoUpdate },
                    { "autoUpdateCheckInterval", payload.AutoUpdateCheckInterval }
                }
            };
            
            // 检查是否有相同类型的任务正在执行
            if (ShouldDiscardTask(task))
            {
                _logger.Warn($"已有配置任务正在执行，丢弃任务: {task.TaskId}");
                
                // 上报任务被丢弃的通知
                await ReportTaskDiscardedAsync(task, "已有配置任务正在执行");
                
                return task; // 返回任务对象，但不加入队列
            }
            
            // 将任务加入队列
            await _taskQueue.EnqueueAsync(task);
            
            return task;
        }
        
        /// <summary>
        /// 根据任务类型创建具体任务
        /// </summary>
        /// <param name="payload">任务负载</param>
        /// <returns>创建的任务</returns>
        private BaseTask CreateTask(TaskDispatchPayloadModel payload)
        {
            BaseTask task = null;
            
            switch (payload.TaskType?.ToUpper())
            {
                case "ADD_GROUP":
                    task = new AddGroupTask
                    {
                        TaskId = payload.TaskId ?? Guid.NewGuid().ToString(),
                        TaskType = TaskType.AddGroup,
                        Priority = (TaskPriority)payload.Priority,
                        Parameters = payload.Params
                    };
                    break;
                    
                case "SEND_MESSAGE":
                    task = new SendMessageTask
                    {
                        TaskId = payload.TaskId ?? Guid.NewGuid().ToString(),
                        TaskType = TaskType.SendMessage,
                        Priority = (TaskPriority)payload.Priority,
                        Parameters = payload.Params
                    };
                    break;
                    
                case "INVITE":
                    task = new InviteFriendTask
                    {
                        TaskId = payload.TaskId ?? Guid.NewGuid().ToString(),
                        TaskType = TaskType.InviteFriend,
                        Priority = (TaskPriority)payload.Priority,
                        Parameters = payload.Params
                    };
                    break;
                    
                case "FORWARD_MESSAGE":
                    task = new ForwardMessageTask
                    {
                        TaskId = payload.TaskId ?? Guid.NewGuid().ToString(),
                        TaskType = TaskType.ForwardMessage,
                        Priority = (TaskPriority)payload.Priority,
                        Parameters = payload.Params
                    };
                    break;
                    
                default:
                    _logger.Warn($"不支持的任务类型: {payload.TaskType}");
                    break;
            }
            
            return task;
        }
    }
} 